package com.improve.frame.db.service;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.improve.frame.common.bean.RequestData;
import com.improve.frame.common.bean.RequestPage;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description
 *      Service基础接口
 * @Author wzxing918
 * @Date 2021-03-31
 * @Version 1.0.0
 **/
public interface BaseService<T> extends IService<T> {
    /**
     * 分页查询
     *
     * @param entity   实体对象
     * @param pageNo   页码
     * @param pageSize 每页显示条数,默认20
     * @return {@link com.baomidou.mybatisplus.core.metadata.IPage<T>}
     */
    IPage<T> page(T entity, Integer pageNo, Integer pageSize);

    /**
     * 分页查询
     *
     * @param entity   实体对象
     * @param pageSize 起始页，默认每页显示条数20
     * @return {@link com.baomidou.mybatisplus.core.metadata.IPage<T>}
     */
    default IPage<T> page(T entity, Integer pageSize) {
        return this.page(entity, 1, pageSize);
    }

    /**
     * 分页查询
     *
     * @param request DTO请求参数
     * @return {@link com.baomidou.mybatisplus.core.metadata.IPage<T>}
     */
    default IPage<T> page(RequestPage<T> request) {
        return this.page(request.getData(), request.getPageNo(), request.getPageSize());
    }

    /**
     * 分页查询
     *
     * @param request DTO请求参数
     * @param tClass  DO类型
     * @param vClass  VO类型
     * @return {@link com.baomidou.mybatisplus.core.metadata.IPage<V>}
     */
    default <D, V> IPage<V> page(RequestPage<D> request, Class<T> tClass, Class<V> vClass) {
        IPage<T> page = this.page(BeanUtil.toBean(request.getData(), tClass), request.getPageNo(), request.getPageSize());
        IPage<V> voPage = new Page<>();
        BeanUtils.copyProperties(page, voPage);
        return voPage;
    }

    /**
     * 列表查询
     *
     * @param dto    DTO对象
     * @param tClass DO类型
     * @param vClass VO类型
     * @return VO列表
     */
    default <D, V> List<V> list(D dto, Class<T> tClass, Class<V> vClass) {
        List<T> list = this.list(new QueryWrapper<>(BeanUtil.toBean(dto, tClass)));
        return list.stream().map(t -> BeanUtil.toBean(t, vClass)).collect(Collectors.toList());
    }


    /**
     * 多表关联分页查询
     *
     * @param map       查询条件map
     * @param pageIndex 起始页
     * @param pageSize  每页显示条数
     * @return {@link com.baomidou.mybatisplus.core.metadata.IPage<T>}
     */
    IPage<T> selectComplex(Map<String, Object> map, int pageIndex, int pageSize);


    /**
     * 批量保存
     *
     * @param dtoList DTO集合
     * @param tClass  DO类型
     * @return 成功：true,失败：false
     */
    @Transactional(rollbackFor = Exception.class)
    default <D> boolean saveBatch(List<D> dtoList, Class<T> tClass) {
        List<T> tList = dtoList.stream().map(dto -> BeanUtil.toBean(dto, tClass)).collect(Collectors.toList());
        return this.saveBatch(tList);
    }

    /**
     * 批量保存
     *
     * @param request DTO请求对象
     * @param tClass  DO类型
     * @return 成功：true,失败：false
     */
    @Transactional(rollbackFor = Exception.class)
    default <D> boolean saveBatch(RequestData<List<D>> request, Class<T> tClass) {
        return this.saveBatch(request.getData(),tClass);
    }

    /**
     * 批量更新
     *
     * @param request DTO请求对象
     * @param tClass  DO类型
     * @return 成功：true,失败：false
     */
    @Transactional(rollbackFor = Exception.class)
    default <D> boolean updateBatchById(RequestData<List<D>> request, Class<T> tClass) {
        List<T> tList = request.getData().stream().map(dto -> BeanUtil.toBean(dto, tClass)).collect(Collectors.toList());
        return this.updateBatchById(tList);
    }

    /**
     * 根据ID查询
     *
     * @param id     主键ID
     * @param vClass VO类型
     * @return VO对象
     */
    default <V> V getById(Serializable id, Class<V> vClass) {
        return BeanUtil.toBean(this.getById(id), vClass);
    }


    /**
     * 根据ID批量查询
     *
     * @param ids ID集合
     * @return DO数据列表
     */
    default List<T> getByIds(Collection<? extends Serializable> ids) {
        return this.getBaseMapper().selectBatchIds(ids);
    }

    /**
     * 根据ID批量查询
     *
     * @param ids    ID集合
     * @param vClass VO类型
     * @return VO数据列表
     */
    default <V> List<V> getByIds(Collection<? extends Serializable> ids, Class<V> vClass) {
        if (CollectionUtils.isEmpty(ids)) {
            return Collections.emptyList();
        }
        List<T> list = this.getBaseMapper().selectBatchIds(ids);
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        return list.stream().map(t -> BeanUtil.toBean(t, vClass)).collect(Collectors.toList());
    }
}
